/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package downloadmanager.downloader;

import downloadmanager.component.MultiSegmentProgressBar;
import downloadmanager.event.DownloaderEventArgs;
import downloadmanager.event.XEvent;
import downloadmanager.event.XEventListener;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import javax.swing.JFrame;
import util.ValueWrapper;

/**
 *
 * @author Administrator
 */
public class DownloadManager {

    private static DownloadManager instance = new DownloadManager();

    public static DownloadManager getInstance() {
        return instance;
    }
    private final List<Downloader> downloads = new ArrayList<Downloader>();
    public final XEvent<DownloaderEventArgs> DownloadEnded = new XEvent<DownloaderEventArgs>();
    public final XEvent<DownloaderEventArgs> DownloadAdded = new XEvent<DownloaderEventArgs>();
    public final XEvent<DownloaderEventArgs> DownloadRemoved = new XEvent<DownloaderEventArgs>();

    public List<Downloader> getDownloads() {
        return new ArrayList<Downloader>(downloads);
    }

    public double getTotalDownloadRate() {
        double total = 0;
        synchronized (downloads) {
            for (int i = 0; i < downloads.size(); i++) {
                if (downloads.get(i).getState() == DownloaderState.Working) {
                    total += downloads.get(i).getRate();
                }
            }
        }

        return total;
    }

    void downloader_StateChanged(Object sender, DownloaderState state) {
        Downloader downloader = (Downloader) sender;

        if (downloader.getState() == DownloaderState.Ended ||
                downloader.getState() == DownloaderState.EndedWithError) {
            onDownloadEnded(downloader);
        }
    }

    public void removeDownload(int index) throws InterruptedException {
        removeDownload(downloads.get(index));
    }

    public void removeDownload(Downloader downloader) throws InterruptedException {
        if (downloader.getState() != DownloaderState.NeedToPrepare ||
                downloader.getState() != DownloaderState.Ended ||
                downloader.getState() != DownloaderState.Paused) {
            downloader.pause();
        }

        synchronized (downloads) {
            downloads.remove(downloader);
        }

        onDownloadRemoved(downloader);
    }

    public void clearEnded() {
        synchronized (downloads) {
            for (int i = downloads.size() - 1; i >= 0; i--) {
                if (downloads.get(i).getState() == DownloaderState.Ended) {
                    Downloader d = downloads.get(i);
                    downloads.remove(i);
                    onDownloadRemoved(d);
                }
            }
        }
    }

    public void pauseAll() throws InterruptedException {
        synchronized (downloads) {
            for (int i = 0; i < this.downloads.size(); i++) {
                this.downloads.get(i).pause();
            }
        }
    }

    public Downloader add(URL rl, String localFile, int requestedSegmentCount, boolean autoStart) {
        Downloader d = new Downloader(rl, localFile, requestedSegmentCount);
        add(d, autoStart);

        return d;
    }

    public Downloader Add(URL rl, String localFile, List<DownloadSegment> segments, RemoteFileInfo remoteInfo, int requestedSegmentCount, boolean autoStart, Date createdDateTime) {
        Downloader d = new Downloader(rl, localFile, segments, remoteInfo, requestedSegmentCount, createdDateTime);
        add(d, autoStart);

        return d;
    }

    public void add(Downloader downloader, boolean autoStart) {
        downloader.StateChanged.subscribe(new downloadmanager.event.XEventListener<DownloaderState>() {

            public void eventFired(Object sender, DownloaderState args) {
                downloader_StateChanged(sender, args);
            }
        });

        synchronized (downloads) {
            downloads.add(downloader);
        }
        onDownloadAdded(downloader, autoStart);

        if (autoStart) {
            downloader.start();
        }
    }

    protected void onDownloadEnded(Downloader d) {
        DownloadEnded.fire(this, new DownloaderEventArgs(d));

    }

    protected void onDownloadAdded(Downloader d, boolean willStart) {
        if (DownloadAdded != null) {
            DownloadAdded.fire(this, new DownloaderEventArgs(d, willStart));
        }
    }

    protected void onDownloadRemoved(Downloader d) {
        DownloadRemoved.fire(this, new DownloaderEventArgs(d));
    }

    public static void main(String[] args) throws MalformedURLException, InterruptedException {

        JFrame f = new JFrame();
        f.setTitle("Test Progress");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        MultiSegmentProgressBar bar = new MultiSegmentProgressBar();
        f.setLayout(new FlowLayout(FlowLayout.LEFT));
        bar.setPreferredSize(new Dimension(300, 20));
        f.add(bar);
        f.pack();
        f.setVisible(true);



        DownloadManager d = DownloadManager.getInstance();
        d.DownloadAdded.subscribe(new XEventListener<DownloaderEventArgs>() {

            public void eventFired(Object sender, DownloaderEventArgs args) {
                System.out.println("Download added");
                System.out.println(args);
            }
        });

        final ValueWrapper<Boolean> ended = new ValueWrapper<Boolean>(false);
        d.DownloadEnded.subscribe(new XEventListener<DownloaderEventArgs>() {

            public void eventFired(Object sender, DownloaderEventArgs args) {
                System.out.println("Download ended");
                System.out.println(args);
                ended.setValue(true);
            }
        });

        d.DownloadRemoved.subscribe(new XEventListener<DownloaderEventArgs>() {

            public void eventFired(Object sender, DownloaderEventArgs args) {
                System.out.println("Download removed");
                System.out.println(args);

            }
        });

        d.add(new URL("http://localhost/at%26t.exe"), "D:\\oh\\yeah\\at&t.exe", 8, false);
        System.out.println("");
        Downloader der = d.getDownloads().get(0);
        der.start();
        bar.setSegmentList(der.getProgressSegmentList());

        while (!ended.getValue()) {
            Thread.sleep(1000);
            System.out.println(der.getProgressSegmentList().toString());
        }
    }
}
